package com.unis.common.excel;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.unis.common.exception.app.AppRuntimeException;
import com.unis.common.util.StrUtil;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by Administrator on 2019/1/16/016.
 * 导出数据结构为List<Object[]>时使用，
 * 若导出结构是List<Object>、List<Map>则使用ExportBeanExcel
 */
public class ExportArrayExcel<T> {
    private static Logger logger = LoggerFactory.getLogger(ExportArrayExcel.class);
    public  final static String  EXCEL_FILE_2003 = "2003";

    /**
     * <p>
     * 通用Excel导出方法,利用反射机制遍历对象的所有字段，将数据写入Excel文件中 <br>
     * 此方法生成2003版本的excel,文件名后缀：xls <br>
     * </p>
     *
     * @param title
     *            表格标题名
     * @param headers
     *            表格头部标题集合
     * @param dataset
     *            需要显示的数据集合,集合中一定要放置符合JavaBean风格的类的对象。此方法支持的
     *            JavaBean属性的数据类型有基本数据类型及String,Date
     * @param out
     *            与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
     * @param pattern
     *            如果有时间数据，设定输出格式。默认为"yyyy-MM-dd HH:mm:ss"
     */
    private void exportExcel2003(String title, String[] headers, List<Object[]> dataset, OutputStream out, String pattern) throws Exception {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        // 设置表格默认列宽度为20个字节
        sheet.setDefaultColumnWidth(20);

        // 生成表头样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置表头样式
        style.setFillForegroundColor(HSSFColor.GREY_50_PERCENT.index);
        //3.17已弃用
        /*style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(CellStyle.BORDER_THIN);
        style.setBorderLeft(CellStyle.BORDER_THIN);
        style.setBorderRight(CellStyle.BORDER_THIN);
        style.setBorderTop(CellStyle.BORDER_THIN);
        style.setAlignment(CellStyle.ALIGN_CENTER);*/
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setAlignment(HorizontalAlignment.CENTER);
        // 生成表头字体
        HSSFFont font = workbook.createFont();
        //font.setBoldweight(Font.BOLDWEIGHT_BOLD);
        font.setBold(true);
        font.setFontName("宋体");
        font.setColor(HSSFColor.WHITE.index);
        font.setFontHeightInPoints((short) 11);
        // 把字体应用到表头的样式
        style.setFont(font);

        // 生成并设置内容样式
        HSSFCellStyle style2 = workbook.createCellStyle();
        style2.setFillForegroundColor(HSSFColor.WHITE.index);
        //3.17已弃用
        /*style2.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style2.setBorderBottom(CellStyle.BORDER_THIN);
        style2.setBorderLeft(CellStyle.BORDER_THIN);
        style2.setBorderRight(CellStyle.BORDER_THIN);
        style2.setBorderTop(CellStyle.BORDER_THIN);
        style2.setAlignment(CellStyle.ALIGN_CENTER);
        style2.setVerticalAlignment(CellStyle.VERTICAL_CENTER);*/
        style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style2.setBorderBottom(BorderStyle.THIN);
        style2.setBorderLeft(BorderStyle.THIN);
        style2.setBorderRight(BorderStyle.THIN);
        style2.setBorderTop(BorderStyle.THIN);
        style2.setAlignment(HorizontalAlignment.CENTER);
        style2.setVerticalAlignment(VerticalAlignment.CENTER);
        // 生成内容字体
        HSSFFont font2 = workbook.createFont();
        //font2.setBoldweight(Font.BOLDWEIGHT_NORMAL);
        font2.setBold(false);
        // 把内容字体应用到内容样式
        style2.setFont(font2);

        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        HSSFCell cellHeader;

        //设置第一列为序号
        sheet.setColumnWidth(0,  (int)((10 + 0.72) * 256));
        cellHeader = row.createCell(0);
        cellHeader.setCellStyle(style);
        cellHeader.setCellValue("序号");

        for (int i = 0; i < headers.length; i++) {
            cellHeader = row.createCell(i+1);
            cellHeader.setCellStyle(style);
            cellHeader.setCellValue(new HSSFRichTextString(headers[i]));
        }

        // 遍历集合数据，产生数据行
        Iterator<Object[]> it = dataset.iterator();
        int index = 0;
        XSSFRichTextString richString;
        Pattern p = Pattern.compile("^//d+(//.//d+)?$");
        Matcher matcher;
        HSSFCell cell;
        Object value;
        Object[] objs;
        String textValue;
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        while (it.hasNext()) {
            index++;
            row = sheet.createRow(index);
            objs = it.next();
            //设置序号
            cell = row.createCell(0);
            cell.setCellStyle(style2);
            cell.setCellValue((Integer) index);

            for (int i = 0; i < headers.length; i++) {
                value = objs[i];
                cell = row.createCell(i+1);
                cell.setCellStyle(style2);

                // 判断值的类型后进行强制类型转换
                textValue = null;
                if (value instanceof Integer) {
                    cell.setCellValue((Integer) value);
                } else if (value instanceof Float) {
                    textValue = String.valueOf(value);
                    cell.setCellValue(textValue);
                } else if (value instanceof Double) {
                    textValue = String.valueOf(value);
                    cell.setCellValue(textValue);
                } else if (value instanceof Long) {
                    cell.setCellValue((Long) value);
                }
                if (value instanceof Boolean) {
                    textValue = "是";
                    if (!(Boolean) value) {
                        textValue = "否";
                    }
                } else if (value instanceof Date) {
                    textValue = sdf.format((Date) value);
                } else {
                    // 其它数据类型都当作字符串简单处理
                    if (value != null) {
                        textValue = value.toString();
                    }
                }
                if (textValue != null) {
                    matcher = p.matcher(textValue);
                    if (matcher.matches()) {
                        // 是数字当作double处理
                        cell.setCellValue(Double.parseDouble(textValue));
                    } else {
						/*richString = new XSSFRichTextString(textValue);
						cell.setCellValue(richString);*/
                        cell.setCellValue(textValue);
                    }
                }
            }
        }
        try{
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("excel导出失败！workbook写入异常！");
            throw new AppRuntimeException("excel导出数据写入失败！");
        }
    }

    /**
     * <p>
     * 导出带有头部标题行的Excel <br>
     * 时间格式默认：yyyy-MM-dd HH:mm:ss <br>
     * </p>
     *
     * @param sheetName 表格标题sheet的名称
     * @param headers 头部标题集合（每一列名称）
     * @param dataset 数据集合（此处适用于List<Object[]>结构数据）
     * @param ouputStream 输出流,一般使用response获取，使用后记得os.flush();os.close();
     * @param version 2003 或者 2007，不传时默认生成2003版本
     */
    private void exportExcel(String sheetName, String[] headers,List<Object[]> dataset, OutputStream ouputStream,String version) throws Exception {

			/*response.setContentType("application/vnd.ms-excel");
    		response.addHeader("Content-Disposition", "attachment;filename="+ fileName + ".xls");*/
            if(!StrUtil.checkIsNaN(version) || EXCEL_FILE_2003.equals(version.trim())){
                exportExcel2003(sheetName, headers, dataset, ouputStream, "yyyy-MM-dd HH:mm:ss");
            }
            /*else{
                exportExcel2007(sheetName, headers,dataset, ouputStream, "yyyy-MM-dd HH:mm:ss");
            }*/
    }

    /**
     * <p>
     * 导出带有头部标题行的Excel <br>
     * 时间格式默认：yyyy-MM-dd HH:mm:ss <br>
     * </p>
     * @param sheetName 表格标题sheet的名称
     * @param headers 头部标题集合（每一列名称）
     * @param dataset 数据集合（此处适用于List<Object[]>结构数据）
     * @param ouputStream 输出流,一般使用response获取，使用后记得os.flush();os.close();
     */
    public void exportExcel(String sheetName, String[] headers,List<Object[]> dataset, OutputStream ouputStream) throws Exception {
        exportExcel2003(sheetName, headers, dataset, ouputStream, "yyyy-MM-dd HH:mm:ss");
    }

}
